<template>
  <div :id="tableName + '_form'">
    <BasicForm ref="onlineFormRef" @register="registerForm" />
  </div>
</template>
<script lang="ts">
  import { ref, reactive, defineComponent, nextTick, unref, toRaw, computed } from 'vue';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useModal } from '/@/components/Modal';
  import { useOnlineFormContext, useEnhance, useFormItems, loadFormFieldsDefVal, getRefPromise } from '../../use/useAutoForm';
  import { pick } from 'lodash-es';
  import { defHttp } from '/@/utils/http/axios';
  import { VALIDATE_FAILED, SUBMIT_FLOW_KEY } from '../../use/FormSchemaFactory';
  import { getToken } from '/@/utils/auth';
  import { goJmReportViewPage } from '/@/utils';

  const urlObject = {
    optPre: '/api-online/online/cgform/api/form/',
    urlButtonAction: '/api-online/online/cgform/api/doButton',
  };
  export default defineComponent({
    name: 'OnlinePopForm',
    components: {
      BasicForm,
    },
    props: {
      id: {
        type: String,
        default: '',
      },
      formTemplate: {
        type: Number,
        default: 1,
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      isTree: {
        type: Boolean,
        default: false,
      },
      pidField: {
        type: String,
        default: '',
      },
      submitTip: {
        type: Boolean,
        default: true,
      },
      modalClass: {
        type: String,
        default: '',
      },
      request: {
        type: Boolean,
        default: true,
      },
      isVxeTableData: {
        type: Boolean,
        default: false,
      },
    },
    emits: ['success', 'rendered', 'dataChange'],
    setup(props, { emit }) {
      console.log('onlineForm-setup》》');
      const { createMessage: $message } = useMessage();
      const [registerVxeFormModal, { openModal: openVxeFormModal }] = useModal();
      const vxeTableId = ref('');
      const onlineFormRef = ref(null);
      const single = ref(true);
      const loading = ref(false);
      const tableType = ref(1);
      const submitFlowFlag = ref(false);
      const isUpdate = ref(false);
      const onlineExtConfigJson = reactive({
        reportPrintShow: 0,
        reportPrintUrl: '',
        joinQuery: 0,
        modelFullscreen: 0,
        modalMinWidth: '',
      });
      const { onlineFormContext, resetContext } = useOnlineFormContext();
      const {
        formSchemas,
        defaultValueFields,
        changeDataIfArray2String,
        tableName,
        dbData,
        checkOnlyFieldValue,
        hasSubTable,
        subTabInfo,
        refMap,
        subDataSource,
        baseColProps,
        createFormSchemas,
        fieldDisplayStatus,
      } = useFormItems(props, onlineFormRef);
      console.log('wang-ffffffffff-001', formSchemas);
      let { EnhanceJS: EnhanceJS2, initCgEnhanceJs: initCgEnhanceJs2 } = useEnhance(onlineFormContext, false);
      const [registerForm, { setProps, validate, resetFields, setFieldsValue, updateSchema, getFieldsValue, scrollToField }] = useForm({
        schemas: formSchemas,
        showActionButtonGroup: false,
        baseColProps,
      });
      const onlineFormDisabled = ref(false);
      function handleFormDisabled() {
        const flag = props.disabled;
        onlineFormDisabled.value = flag;
        setProps({ disabled: flag });
      }
      async function show(status, record2, param) {
        console.log('OnlinePopForm新增编辑进入表单》》form', record2);
        await resetFields();
        dbData.value = '';
        const flag = unref(status);
        isUpdate.value = flag;
        if (flag) {
          await edit(record2);
        }
        await nextTick(() => {
          if (!flag && param) {
            setFieldsValue(param);
          }
          handleDefaultValue2();
          handleCgButtonClick('js', 'loaded');
          handleFormDisabled();
        });
      }
      function handleDefaultValue2() {
        if (unref(isUpdate) === false) {
          const fieldProperties = toRaw(defaultValueFields[tableName.value]);
          loadFormFieldsDefVal(fieldProperties, (values) => {
            setFieldsValue(values);
          });
        }
      }
      async function edit(record2) {
        let formData = await getFormData(record2.id);
        if (!formData || Object.keys(formData).length == 0) {
          formData = { ...toRaw(record2) };
        }
        dbData.value = Object.assign({}, formData);
        const arr = realFormFieldNames.value;
        let values = pick(formData, ...arr);
        if (props.isVxeTableData === true) {
          values = Object.assign({}, values, record2);
        }
        await setFieldsValue(values);
      }
      const realFormFieldNames = computed(() => {
        const arr = formSchemas.value;
        const names = [];
        for (const a of arr) {
          names.push(a.field);
        }
        return names;
      });
      function getFormData(dataId) {
        const url = `${urlObject.optPre}${props.id}/${dataId}`;
        return new Promise((resolve, reject) => {
          defHttp
            .get({ url }, { isTransformResponse: false })
            .then((res) => {
              if (res.success) {
                resolve(res.data);
              } else {
                reject();
                $message.warning(res.msg);
              }
            })
            .catch(() => {
              reject();
            });
        });
      }
      async function createRootProperties(data) {
        tableType.value = data.head.tableType;
        tableName.value = data.head.tableName;
        single.value = data.head.tableType == 1;
        handleExtConfigJson(data.head.extConfigJson);
        createFormSchemas(data.schema.properties, data.schema.required, checkOnlyFieldValue);
        EnhanceJS2 = initCgEnhanceJs2(data.enhanceJs);
        emit('rendered', onlineExtConfigJson);
        const formRefObject = await getRefPromise(onlineFormRef);
        formRefObject.$formValueChange = (field2, value) => {
          onValuesChange(field2, value);
        };
      }
      function handleExtConfigJson(jsonStr) {
        let extConfigJson2 = { reportPrintShow: 0, reportPrintUrl: '', joinQuery: 0, modelFullscreen: 1, modalMinWidth: '' };
        if (jsonStr) {
          extConfigJson2 = JSON.parse(jsonStr);
        }
        Object.keys(extConfigJson2).map((k) => {
          onlineExtConfigJson[k] = extConfigJson2[k];
        });
      }
      function handleSubmit() {
        if (single.value === true) {
          handleSingleSubmit();
        } else {
          handleOne2ManySubmit();
        }
      }
      function handleOne2ManySubmit() {
        validateAll().then((formData) => {
          handleApplyRequest(formData);
        });
      }
      function validateAll() {
        const temp = {};
        return new Promise((resolve, reject) => {
          validate().then(
            (values) => resolve(values),
            ({ errorFields }) => {
              if (errorFields && errorFields.length > 0) {
                scrollToField(errorFields[0][0]);
              }
              reject(VALIDATE_FAILED);
            }
          );
        })
          .then((result) => {
            Object.assign(temp, changeDataIfArray2String(result));
            return validateSubTableFields();
          })
          .then((allTableData) => {
            Object.assign(temp, allTableData);
            return Promise.resolve(temp);
          })
          .catch((e) => {
            if (e === VALIDATE_FAILED || (e == null ? void 0 : e.code) === VALIDATE_FAILED) {
              $message.warning('校验未通过');
              if (e.key) {
                changeTab(e.key);
              }
            } else {
              console.error(e);
            }
            return Promise.reject(null);
          });
      }
      function changeTab(key) {
        const arr = subTabInfo.value;
        for (let i = 0; i < arr.length; i++) {
          if (key == arr[i].key) {
            subActiveKey.value = i + '';
            break;
          }
        }
      }
      function validateSubTableFields() {
        return new Promise(async (resolve, reject) => {
          let subData = {};
          try {
            let arr = subTabInfo.value;
            for (let i = 0; i < arr.length; i++) {
              let key = arr[i].key;
              let instance = refMap[key].value;
              if (instance instanceof Array) {
                instance = instance[0];
              }
              if (arr[i].relationType == 1) {
                try {
                  let subFormData = await instance.getAll();
                  subData[key] = [];
                  subData[key].push(subFormData);
                } catch (e) {
                  throw { code: VALIDATE_FAILED, key };
                }
              } else {
                let errMap = await instance.fullValidateTable();
                if (errMap) {
                  throw { code: VALIDATE_FAILED, key };
                }
                subData[key] = instance.getTableData();
              }
            }
          } catch (e) {
            reject(e);
          }
          resolve(subData);
        });
      }
      async function handleSingleSubmit() {
        try {
          let values = await validate();
          values = Object.assign({}, dbData.value, values);
          values = changeDataIfArray2String(values);
          loading.value = true;
          handleApplyRequest(values);
        } finally {
          loading.value = false;
        }
      }
      function handleApplyRequest(formData) {
        customBeforeSubmit2(context, formData)
          .then(() => {
            doApplyRequest(formData);
          })
          .catch((msg) => {
            $message.warning(msg);
          });
      }
      function triggleChangeValues(values, id, target) {
        if (id && target) {
          if (target.setValues) {
            target.setValues(values);
          } else {
            target.setValues([
              {
                rowKey: id,
                values,
              },
            ]);
          }
        } else {
          setFieldsValue(values);
        }
      }
      function triggleChangeValue(field2, value) {
        const obj = {};
        obj[field2] = value;
        setFieldsValue(obj);
      }
      const subActiveKey = ref('0');
      const subFormHeight = ref(300);
      const subTableHeight = ref(340);
      function getSubTableForeignKeyValue(key) {
        if (isUpdate.value === true) {
          const formData = dbData.value;
          return getValueIgnoreCase(formData, key);
        }
        return '';
      }
      function getValueIgnoreCase(data, key) {
        if (data) {
          let temp = data[key];
          if (!temp && temp !== 0) {
            temp = data[key.toLowerCase()];
            if (!temp && temp !== 0) {
              temp = data[key.toUpperCase()];
            }
          }
          return temp;
        }
        return '';
      }
      function handleSubFormChange(valueObj, tableKey) {
        if (EnhanceJS2 && EnhanceJS2[tableKey + '_onlChange']) {
          const tableChangeObj = EnhanceJS2[tableKey + '_onlChange']();
          const columnKey = Object.keys(valueObj)[0];
          if (tableChangeObj[columnKey]) {
            let subRef = refMap[tableKey].value;
            if (subRef instanceof Array) {
              subRef = subRef[0];
            }
            const formEvent = subRef.getFormEvent();
            const event = Object.assign(
              {
                column: { key: columnKey },
                value: valueObj[columnKey],
              },
              formEvent
            );
            tableChangeObj[columnKey].call(onlineFormContext, onlineFormContext, event);
          }
        }
      }
      function handleValueChange(event, tableKey) {
        if (EnhanceJS2 && EnhanceJS2[tableKey + '_onlChange']) {
          const tableChangeObj = EnhanceJS2[tableKey + '_onlChange'](onlineFormContext);
          if (tableChangeObj[event.column.key]) {
            tableChangeObj[event.column.key].call(onlineFormContext, onlineFormContext, event);
          }
        }
      }
      function handleAdded(sub, event) {
        console.log('handleAdded', sub, event);
      }
      function getSubTableAuthPre(table) {
        return 'online_' + table + ':';
      }
      async function onValuesChange(columnKey, value) {
        const oldFormData = dbData.value;
        if (oldFormData[columnKey] != value) {
          emit('dataChange', columnKey);
        }
        if (!EnhanceJS2 || !EnhanceJS2['onlChange']) {
          return false;
        }
        if (!columnKey) {
          return false;
        }
        const tableChangeObj = EnhanceJS2['onlChange']();
        if (tableChangeObj[columnKey]) {
          const formData = await getFieldsValue();
          const event = {
            row: formData,
            column: { key: columnKey },
            value,
          };
          tableChangeObj[columnKey].call(onlineFormContext, onlineFormContext, event);
        }
      }
      function handleCgButtonClick(optType, buttonCode) {
        if ('js' == optType) {
          if (EnhanceJS2 && EnhanceJS2[buttonCode]) {
            EnhanceJS2[buttonCode].call(onlineFormContext, onlineFormContext);
          }
        } else if ('action' == optType) {
          const formData = dbData.value;
          const params = {
            formId: props.id,
            buttonCode,
            dataId: formData.id,
            uiFormData: Object.assign({}, formData),
          };
          defHttp
            .post(
              {
                url: `${urlObject.urlButtonAction}`,
                params,
              },
              { isTransformResponse: false }
            )
            .then((res) => {
              if (res.success) {
                $message.success('处理完成!');
              } else {
                $message.warning('处理失败!');
              }
            });
        }
      }
      function clearSubRows(tbname) {
        const instance = refMap[tbname].value;
        const rows = [...instance.getNewDataWithId(), ...subDataSource.value[tbname]];
        if (!rows || rows.length == 0) {
          return false;
        }
        const ids = [];
        for (const i of rows) {
          ids.push(i.id);
        }
        instance.removeRowsById(ids);
      }
      function addSubRows(tbname, rows) {
        if (!rows) {
          return false;
        }
        const instance = refMap[tbname].value;
        if (typeof rows == 'object') {
          instance.addRows(rows, true);
        } else {
          $message.error('添加子表数据,参数不识别!');
        }
      }
      function clearThenAddRows(tbname, rows) {
        clearSubRows(tbname);
        addSubRows(tbname, rows);
      }
      function changeOptions(field2, options) {
        if (!options && options.length <= 0) {
          options = [];
        }
        options.map((item) => {
          if (!item.hasOwnProperty('label')) {
            item['label'] = item.text;
          }
        });
        updateSchema({
          field: field2,
          componentProps: {
            options,
          },
        });
      }
      function customBeforeSubmit2(that, formData) {
        if (EnhanceJS2 && EnhanceJS2['beforeSubmit']) {
          return EnhanceJS2['beforeSubmit'](that, formData);
        } else {
          return Promise.resolve();
        }
      }
      function handleCustomFormSh(show2, hide) {
        const plain = toRaw(fieldDisplayStatus);
        if (show2 && show2.length > 0) {
          Object.keys(plain).map((k) => {
            if (!k.endsWith('_load') && show2.indexOf(k) < 0) {
              fieldDisplayStatus[k] = false;
            }
          });
        } else if (hide && hide.length > 0) {
          Object.keys(plain).map((k) => {
            if (hide.indexOf(k) >= 0) {
              fieldDisplayStatus[k] = false;
            }
          });
        }
      }
      async function handleCustomFormEdit(record2) {
        console.log('自定义弹窗打开online表单》》form', record2);
        await resetFields();
        dbData.value = '';
        isUpdate.value = true;
        await edit(record2);
        await nextTick(() => {
          handleCgButtonClick('js', 'loaded');
        });
      }
      function getSubTableInstance(tableName2) {
        let instance = refMap[tableName2].value;
        if (instance instanceof Array) {
          instance = instance[0];
        }
        return instance;
      }
      function onOpenReportPrint() {
        const url = onlineExtConfigJson.reportPrintUrl;
        const id = dbData.value.id;
        const token = getToken();
        goJmReportViewPage(url, id, token);
      }
      function openSubFormModalForAdd(sub) {
        console.log(sub);
        vxeTableId.value = sub.id;
        openVxeFormModal(true);
      }
      function openSubFormModalForEdit(sub) {
        console.log(sub);
      }
      function doApplyRequest(formData) {
        Object.keys(formData).map((key) => {
          if (Array.isArray(formData[key])) {
            if (formData[key].length == 0) {
              formData[key] = '';
            }
          }
        });
        console.log('提交pop表单数据》》》form:', formData);
        if (props.request == false) {
          emit('success', formData);
        } else {
          const url = `${urlObject.optPre}${props.id}?tabletype=${tableType.value}`;
          console.log('提交pop表单url》》》url:', url);
          if (submitFlowFlag.value === true) {
            formData[SUBMIT_FLOW_KEY] = 1;
          }
          const method = isUpdate.value === true ? 'put' : 'post';
          defHttp
            .request({ url, method, params: formData }, { isTransformResponse: false })
            .then((res) => {
              if (res.success) {
                if (res.data) {
                  if (!formData.id) {
                    formData['id'] = res.data;
                  }
                }
                emit('success', formData);
                dbData.value = formData;
                isUpdate.value = true;
                $message.success('操作成功!');
              } else {
                $message.warning(res.msg);
              }
            })
            .finally(() => {
              loading.value = false;
            });
        }
      }
      async function recoverFormData() {
        const record2 = dbData.value;
        const arr = realFormFieldNames.value;
        const values = pick(record2, ...arr);
        if (record2) {
          await setFieldsValue(values);
        } else {
          const temp = {};
          for (const key of arr) {
            temp[key] = '';
          }
          await setFieldsValue(temp);
        }
      }
      const context = {
        tableName,
        loading,
        subActiveKey,
        onlineFormRef,
        getFieldsValue,
        setFieldsValue,
        submitFlowFlag,
        subFormHeight,
        subTableHeight,
        refMap,
        triggleChangeValues,
        triggleChangeValue,
        sh: fieldDisplayStatus,
        clearSubRows,
        addSubRows,
        clearThenAddRows,
        changeOptions,
        isUpdate,
        getSubTableInstance,
      };
      resetContext(context);
      return {
        tableName,
        onlineFormRef,
        registerForm,
        loading,
        subActiveKey,
        hasSubTable,
        subTabInfo,
        refMap,
        subFormHeight,
        getSubTableForeignKeyValue,
        isUpdate,
        handleSubFormChange,
        subTableHeight,
        onlineFormDisabled,
        subDataSource,
        getSubTableAuthPre,
        handleAdded,
        handleValueChange,
        openSubFormModalForAdd,
        openSubFormModalForEdit,
        registerVxeFormModal,
        vxeTableId,
        show,
        createRootProperties,
        handleSubmit,
        sh: fieldDisplayStatus,
        handleCgButtonClick,
        handleCustomFormSh,
        handleCustomFormEdit,
        dbData,
        onOpenReportPrint,
        onlineExtConfigJson,
        recoverFormData,
      };
    },
  });
</script>
<style scoped></style>
